/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.model.codes;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.zhiqim.kernel.constants.CodeConstants;
import org.zhiqim.kernel.enumerated.CipherMode;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Strings;

/**
 * AES加解密，默认ECB模式
 * 1、AES/ECB/PKCS5Padding
 * 2、AES/CBC/PKCS5Padding
 *
 * @version v1.0.0 @author zouzhigang 2018-8-22 新建与整理
 */
public class AES implements CodeConstants
{
    /**********************************************************************************/
    //标准加解密
    /**********************************************************************************/
    
    /**
     * 标准加密，支持指定模式和填充方式
     * 
     * @param src           原数据
     * @param mode          密码器模式
     * @param keyBytes      8位长度的密钥字节数组
     * @return              加密后数据
     * @throws Exception    异常
     */
    public static byte[] encrypt(byte[] src, CipherMode mode, byte[] keyBytes) throws Exception
    {
        Asserts.as((keyBytes != null && keyBytes.length > 0)?null:"密钥不能为空");
        
        Cipher cipher = Cipher.getInstance(_AES_ + "/" + mode + "/" + _PKCS5_PADDING_);
        mode.initCipherEncrypt(cipher, new SecretKeySpec(keyBytes, _AES_));
        
        return cipher.doFinal(src);
    }
    
    /**
     * 标准解密
     * 
     * @param src           原数据
     * @param mode          密码器模式
     * @param keyBytes      8位长度的密钥字节数组
     * @return              解密后数据
     * @throws Exception    异常
     */
    public static byte[] decrypt(byte[] src, CipherMode mode, byte[] keyBytes) throws Exception 
    {
        Asserts.as((keyBytes != null && keyBytes.length > 0)?null:"密钥不能为空");
        
        Cipher cipher = Cipher.getInstance(_AES_ + "/" + mode + "/" + _PKCS5_PADDING_);
        mode.initCipherDecrypt(cipher, new SecretKeySpec(keyBytes, _AES_));
        
        return cipher.doFinal(src);
    }
    
    /**********************************************************************************/
    //ECB模式&字符串密钥 加解密
    /**********************************************************************************/
    
    /**
     * ECB模式加密
     * 
     * @param src           原数据
     * @param key           8位长度的密钥字符串
     * @return              加密后数据
     * @throws Exception    异常
     */
    public static byte[] encrypt(byte[] src, String key) throws Exception
    {
        return encrypt(src, CipherMode.ECB, key.getBytes(_UTF_8_C_));
    }
    
    /**
     * ECB模式解密
     * 
     * @param src           原数据
     * @param key           8位长度的密钥字符串
     * @return              解密后数据
     * @throws Exception    异常
     */
    public static byte[] decrypt(byte[] src, String key) throws Exception 
    {
        return decrypt(src, CipherMode.ECB, key.getBytes(_UTF_8_C_));
    }
    
    /**********************************************************************************/
    //ECB模式&字符串密钥&Base64返回字符串 加解密
    /**********************************************************************************/
    
    /**
     * ECB模式加密，返回Base64字符串
     * 
     * @param src           原数据
     * @param key           密钥字符串
     * @return              加密后数据
     * @throws Exception    异常
     */
    public static String encryptBase64(byte[] src, String key) throws Exception
    {
        return Base64.encode(encrypt(src, CipherMode.ECB, key.getBytes(_UTF_8_C_)));
    }
    
    /**
     * ECB模式解密，返回Base64字符串
     * 
     * @param src           原数据
     * @param key           密钥字符串
     * @return              解密后数据
     * @throws Exception    异常
     */
    public static byte[] decryptBase64(String src, String key) throws Exception 
    {
        return decrypt(Base64.decode(src), CipherMode.ECB, key.getBytes(_UTF_8_C_));
    }
    
    /**
     * ECB模式解密，返回Base64字符串
     * 
     * @param src           原数据
     * @param key           8位长度的密钥字符串
     * @return              解密后数据
     * @throws Exception    异常
     */
    public static String decryptBase64UTF8(String src, String key) throws Exception
    {
        return Strings.newStringUTF8(decryptBase64(src, key));
    }
}
